\documentclass[twoside,colorback,accentcolor=tud4c,11pt]{tudreport}
\usepackage{ngerman}

\usepackage[utf8]{inputenc}

\usepackage{listings}
\lstset{
numbers=left,
numberstyle=\footnotesize,
frame=l,
breaklines=true,
basicstyle=\footnotesize,
showstringspaces=false
}

\usepackage[stable]{footmisc}
\usepackage[ngerman,pdfview=FitH,pdfstartview=FitV]{hyperref}

\usepackage{graphicx}
\usepackage{caption}
\usepackage{subcaption}

\usepackage{booktabs}
\usepackage{multirow}
\usepackage{longtable}

\newlength{\longtablewidth}
\setlength{\longtablewidth}{0.675\linewidth}

\title{Praktikum adaptive Computersysteme}
\subtitle{Ausarbeitung\\3. Phase: Bildbearbeitung}
\subsubtitle{Wilko Kunert, Alexander Schleich}
\lowertitleback{\hfill\today}
\institution{Embedded Systems \& Applications}

\begin{document}
\maketitle

\tableofcontents

\chapter{C-Programm}

Ziel der 3. Phase des Praktikums adaptive Computersysteme ist die Programmierung eines Kontrastspreizers in C. Als Vorlage dient dabei ein bestehender Aufheller, dessen Code wir zu diesem Zweck abändern sollen. Das Ergebnis unserer Implementierung ist in Abbildung~\ref{fig:kontrastspreizung}, der Code in den Abbildungen~\ref{fig:initialisierung}~bis~\ref{fig:ausgabe} zu sehen.

\begin{figure}[h]
\centering
\begin{subfigure}[b]{0.45\textwidth}
\centering
\includegraphics[width=\textwidth]{graphics/lena256.png}
\caption{lena256.pgm}
\end{subfigure}
\begin{subfigure}[b]{0.45\textwidth}
\centering
\includegraphics[width=\textwidth]{graphics/lena256c.png}
\caption{lena256c.pgm}
\end{subfigure}
\caption{Kontrastspreizung}
\label{fig:kontrastspreizung}
\end{figure}

Abbildung~\ref{fig:initialisierung} beinhaltet den Code für die Initialisierung der Variablen und ist zum größten Teil identisch mit der Vorlage des Aufhellers. Neu sind die Variablen für die minimalen (\textit{minValue}) sowie maximalen (\textit{maxValue}) Grauwerte, deren Abstand zueinander (\textit{numberOfGreyValues}) und die geplante Schrittweite der Spreizung (\textit{stepSize}).

Abbildung~\ref{fig:bildbearbeitung} zeigt den eigentlichen Programmablauf: Nach dem Einlesen des Bilds werden in den Zeilen~70~bis~80 die minimalen und maximalen Grauwerte ermittelt und in den entsprechenden Variablen (\textit{minValue}, \textit{maxValue}) gespeichert. Anschließend wird aus dem Abstand zwischen Minimum und Maximum (\textit{numberOfGreyValues}) die Schrittweite der Spreizung (\textit{stepSize}) nach der Formel \textit{255 / numberOfGreyValues} berechnet. Mit Hilfe der ermittelten Schrittweite wird in der zweiten Schleife (Zeilen~91~bis~104) das Bild gespreizt: Dafür wird von jedem Pixel der momentane Grauwert das bereits ermittelte Minimum abgezogen und das Ergebnis mit der Schrittweite multipliziert (Zeile~93).

In Abbildung~\ref{fig:ausgabe} befindet sich der Code für das Speichern des modifizierten Bilds und für die Ausgabe von diversen (Debugging-)Informationen.

\begin{figure}[h]
\centering
\begin{minipage}{\linewidth}
\lstset{language=C,linewidth=0.9\linewidth,firstnumber=1}
\begin{lstlisting}
// Kontrastspreizung
// Aufruf mit: ./contrast Eingabe.pgm Ausgabe.pgm

#include "stdio.h"

main(
     int argc,     // Anzahl Kommandozeilenparameter + Programmname
     char *argv[]  // Programmname + Kommandozeilenparameter als Strings
     )
{
  // Speicher fuer ganzes 256x256 Bild, Werte 0 ... 255
  unsigned char image[256][256];

  // Iterationsvariable
  unsigned int n;

  // maximaler Grauwert
  unsigned int maxValue = 0;

  // minimaler Grauwert
  unsigned int minValue = 256;

  // maximale Anzahl verschiedener Grauwerte
  unsigned int numberOfGreyValues;

  // Schrittgroesse fuer Berechnung neuer Grauwerte
  double stepSize;

  // Zeiger auf aktuellen Bildpunkt
  unsigned char *p;

  // Neuer Grauwert. Wichtig: Wertebereich hier ist 0 ... 65535
  unsigned short w;

  // Eingabe- und Ausgabedatei
  FILE *infile, *outfile;

  // Aufrufparameter pruefen
  if (argc != 3) {
    printf("Falscher Aufruf, richtig: `./contrast Eingabe.pgm Ausgabe.pgm'\n");
    exit(1);
  }

  // Eingabedatei oeffnen
  if ((infile = fopen(argv[1], "r")) == NULL) {
    printf("Eingabedatei %s konnte nicht geoeffnet werden.\n", argv[1]);
    exit(2);
  }

  // Ausgabedatei oeffnen
  if ((outfile = fopen(argv[2], "w")) == NULL) {
    printf("Ausgabedatei %s konnte nicht geoeffnet werden.\n", argv[2]);
    exit(3);
  }
\end{lstlisting}
\end{minipage}
\caption{contrast.c - Initialisierung}
\label{fig:initialisierung}
\end{figure}

\begin{figure}[h]
\centering
\begin{minipage}{\linewidth}
\lstset{language=C,linewidth=0.9\linewidth,firstnumber=56}
\begin{lstlisting}
  // Reiche PGM Kopfdatensatz direkt durch
  fgets((void*)image, 80, infile);
  fputs((void*)image,  outfile);
  fgets((void*)image, 80, infile);
  fputs((void*)image,  outfile);
  fgets((void*)image, 80, infile);
  fputs((void*)image,  outfile);

  // lese gesamtes Feld von Bildpunkten auf einen Satz
  fread(image, sizeof(unsigned char), 256*256, infile);
  
  // *************** Ab hier Bildbearbeitung ************************

  // finde Minima und Maxima aller Grauwerte
  for (n = 0, p = (void*) image; n < 256*256; ++p, ++n) 
    {
      if(*p < minValue)
	{
	  minValue = *p;	
	}
      if(*p > maxValue)
	{
	  maxValue = *p;
	}
    }

  // berechne Werte
  numberOfGreyValues = maxValue - minValue;
  stepSize = (double) (255) / (double)(numberOfGreyValues);

  // nur fuer Ausgabe interessant
  unsigned int tempMin = 255;
  unsigned int tempMax = 0;

  // setze neue Grauwerte
  for (n = 0, p = (void*) image; n < 256*256; ++p, ++n) 
    {
      *p = (*p - minValue) * stepSize;

      // nur fuer Ausgabe interessant
      if(*p < tempMin)
	{
	  tempMin = *p;	
	}
      if(*p > tempMax)
	{
	  tempMax = *p;
	}
    }

  // *************** Ende der Bildbearbeitung ************************
\end{lstlisting}
\end{minipage}
\caption{contrast.c - Bildbearbeitung}
\label{fig:bildbearbeitung}
\end{figure}

\begin{figure}[h]
\centering
\begin{minipage}{\linewidth}
\lstset{language=C,linewidth=0.9\linewidth,firstnumber=108}
\begin{lstlisting}
  // Ausgabe fuer Debugging
  printf("\r\nminimaler Grauwert im Bild vorher %u \r\n", minValue);
  printf("maximaler Grauwert im Bild vorher %u \r\n\r\n", maxValue);
  printf("numberOfGreyVariables = %u \r\n\r\n", numberOfGreyValues);
  printf("stepsize = %f \r\n\r\n", stepSize);
  printf("minimaler Grauwert im Bild nachher %u \r\n", tempMin);
  printf("maximaler Grauwert im Bild nachher %u \r\n\r\n", tempMax);

  // gebe gesamtes Feld von Bildpunkten auf einen Satz aus
  fwrite(image, sizeof(unsigned char), 256*256, outfile);

  // Dateien schliessen
  fclose(infile);
  fclose(outfile);

  // Programm mit Status `Kein Fehler' beenden
  exit(0);

}
\end{lstlisting}
\end{minipage}
\caption{contrast.c - Ausgabe}
\label{fig:ausgabe}
\end{figure}

\chapter{Diskussion}

Im Rahmen der nächsten Phasen sollen die zeitintensiven Abläufe des reinen C-Programms in die Hardware ausgelagert werden. Dabei steht die Parallelisierung im Vordergrund, vor allem von Aufgaben, die ansonsten in Schleifen abgearbeitet werden. Unsere Implementierung verfügt über zwei solcher Schleifen, die sich entsprechend auslagern ließen und teilweise parallelisiert abgearbeitet werden könnten (zum Beispiel durch mehrere Vergleiche in einem Takt). Der Flaschenhals bei dieser Umsetzung ist der Transfer der Daten von der CPU zur RCU, deshalb sollten die zu verarbeitenden Daten von der Hardware eigenständig eingelesen werden, um Burst-Transfer nutzen zu können. Außerdem können bereits während des Einlesens das Minimum und das Maximum der Grauwerte ermittelt und erst beim wegspeichern entsprechend gespreizt werden. Damit entfallen die zusätzlichen Schleifen für die Berechnung.

\end{document}
